# 函数
# 定义
'''
def 函数名(参数):
    函数代码(缩进)
    函数代码(缩进)
    函数代码(缩进)

函数中
    1.函数名() 表示函数调用
    2. 单个函数名 表示将函数作为变量可以进行传值

'''


def mutil(a, b):
    return a * b


print(mutil)
print(mutil(2, 3))
fun1 = mutil
print(fun1(3, 4))

# 迭代函数
'''
递归函数：
    1.函数中必须有停止递归代码
    2.函数中必须调用自身，并且传入参数必须不断变化
'''


# 求阶乘函数  5 => 1 * 2 * 3 * 4 * 5

def fun1(n):
    num = 1
    for i in range(1, n + 1):
        num *= i
    return num


print(fun1(5))


def fun2(n):
    if (n == 1):
        return 1
    else:
        return n * fun2(n - 1)


print(fun2(5))

# 函数参数
'''
参数类型：
    1.位置参数(普通参数)
    2.可变长参数 
        2.1 参数命名需要用 * 标记
        2.2 参数的类型为tuple
    
    3.默认参数
        3.1 默认参数需要放在位置参数之后定义
        3.2 默认参数调用时，如果给定值，那么就覆盖默认值
        
    4.关键字参数
        4.1 关键字参数需要用 ** 标记
        4.2 参数传入时需要用 变量名=值方式传入，并且可以传入多个
        4.3 参数对应类型为字典类型
        4.4 参数使用时可以通过get获取传入key对应value
        

'''


# print("参数1", "参数2", "参数3")


def func3(*args):
    print(args, type(args))


func3("参数1", "参数2", "参数3")


def multi(*args):
    num = 1
    for i in args:
        num *= i
    return num


print(multi(4, 5, 6))


def fun4(age, name="张三"):
    print("name:{} age:{}".format(name, age))


fun4(18)
fun4(age=20, name="李四")


def fun5(age, *args, name="张三"):
    print("name:{} age:{} args:{}".format(name, age, args))


# 调用默认参数需要手动指定
fun5(19, '女', '文科一班', name='李四')


def fun6(age, name="张三", *args):
    print("name:{} age:{} args:{}".format(name, age, args))


# 注意默认参数所在位置
fun6(19, '女', '文科一班')


def fun7(**args):
    print("args:{} type:{}".format(args, type(args)))


fun7(name="zhangsan", age="20", gender="nv")


def fun8(**args):
    for k, v in args.items():
        print("Key:{} value:{}".format(k, v))
    print(args.get("name"))


fun8(name1="zhangsan", age="20", gender="nv")

# 匿名函数
# 格式:  函数名 = lambda 参数名 : 参数调用及返回数据
f = lambda x, y: x + y

print(f(2, 3))


# return
# Python中的return可以给定多个值

def func2(x, y):
    return x, y, x + y


a, b, c = func2(2, 3)
print("{} + {} = {}".format(a, b, c))


# 给定一个 1-10 的列表，对列表中的数据进行扩大两倍，然后再返回列表

def fun4(list):
    new_list = []
    for i in list:
        new_list.append(i * 2)
    return new_list

print(fun4(range(1, 11)))

# 问题？ 如果这个列表中的数据有一亿条 ，那么上面的func4函数最终的结果是2亿条数据，内存占用扩大一倍


def fun5(list):
    for i in list:
        print("******")
        yield i * 2

for i in fun5(range(1, 11)):
    print("%%%%")
    print(i)


# yield 优点：
#    1.不占用过多的内存空间
#    2.提高系统运行速度


